/**
 * ***************************************
 * @file ymodem.c
 * @author : {Lek} (emimand1010@gmail.com)
 * @brief : 
 * @version 0.1
 * @date : 2024-11-23
 * @copyright Copyright (c) 2024
 * 
 * ***************************************
 */


#include "ymodem.h"
#include "driver/usb_serial_jtag_vfs.h"
#include "driver/uart_vfs.h"
#include "driver/usb_serial_jtag.h"
#include "hal/usb_serial_jtag_ll.h"

#ifdef YMODEM_USING_CRC_TABLE
static const uint16_t ccitt_table[256] =
    {
        0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
        0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
        0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
        0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
        0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
        0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
        0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
        0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
        0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
        0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
        0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
        0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
        0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
        0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
        0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
        0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
        0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
        0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
        0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
        0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
        0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
        0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
        0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
        0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
        0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
        0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
        0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
        0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
        0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
        0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
        0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
        0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0};
static uint16_t CRC16(unsigned char *q, int len)
{
    uint16_t crc = 0;

    while (len-- > 0)
        crc = (crc << 8) ^ ccitt_table[((crc >> 8) ^ *q++) & 0xff];
    return crc;
}
#else

static void Ymodem_Printf(uint8_t *Buff, uint32_t ulLen)
{
    uint32_t chunk_size = AT_TXBUF_SIZE; // 最大传输量为 128 字节
    uint32_t remaining = ulLen;          // 剩余的数据长度
    uint32_t offset = 0;

    while (remaining > 0)
    {
        uint32_t send_len = (remaining < chunk_size) ? remaining : chunk_size;
        usb_serial_jtag_write_bytes((const void *)(Buff + offset), send_len, portMAX_DELAY);
        usb_serial_jtag_ll_txfifo_flush(); // 刷新发送缓冲区
        offset += send_len;
        remaining -= send_len;
    }
}

static uint16_t CRC16(uint8_t *q, int len)
{
    uint16_t crc;
    char i;

    crc = 0;
    while (--len >= 0)
    {
        crc = crc ^ (int)*q++ << 8;
        i = 8;
        do
        {
            if (crc & 0x8000)
                crc = crc << 1 ^ 0x1021;
            else
                crc = crc << 1;
        } while (--i);
    }

    return (crc);
}
#endif

static uint32_t RYM_ReadData(uint8_t *buf, uint32_t DataLen, uint32_t TimerTick)
{
    uint32_t ulDataLen = 0; // 初始化已读取字节数
    uint32_t bytesRead;
    uint32_t startTime = TimerTick; // 记录函数开始时的时间戳

    // 循环读取直到读取到完整的数据或函数超时
    while (ulDataLen < DataLen)
    {
        // 调用usb_serial_jtag_read_bytes进行数据读取，超时设为100ms
        bytesRead = usb_serial_jtag_read_bytes(buf + ulDataLen, DataLen - ulDataLen, 100);

        // 如果读取返回错误（bytesRead <= 0），则退出
        if (bytesRead <= 0)
        {
            // 错误处理，可以根据需求进行相应的处理
            return ulDataLen; // 返回已读取的字节数
        }

        ulDataLen += bytesRead; // 更新已读取字节数

        // 检查是否超时
        if (TimerTick - startTime >= TimerTick)
        {                     // 如果超过函数设定的超时时间，退出
            return ulDataLen; // 返回已读取字节数
        }
    }

    return ulDataLen; // 返回完整读取的字节数
}

/**
 * @brief : 接收握手阶段
 *
 * @param  : pxRYM_Ag - {参数说明}:
 * @param  : TimerOut - {参数说明}:
 * @return : int - {函数返回值说明}
 */
static int RYM_Readhandshake(RYM_t *pxRYM_Ag, uint32_t TimerOut)
{
    enum rym_code code = 0;
    uint32_t ulDataLen = 0;
    uint32_t uldata_sz = 0;
    size_t i = 0;
    uint16_t recv_crc = 0;
    uint16_t cal_crc = 0;
    //static uint8_t ucCanErrCount = 0;
    for (i = 0; i < TimerOut; i++)
    {

        Ymodem_Printf((uint8_t[]){(uint8_t)RYM_CODE_C}, 1);
        ulDataLen = RYM_ReadData((uint8_t *)&code, 1, RYM_CHD_INTV_TICK);

        if (code == RYM_CODE_SOH)
        {
            uldata_sz = _RYM_SOH_PKG_SZ;
            break;
        }
        else if (code == RYM_CODE_STX)
        {
            uldata_sz = _RYM_STX_PKG_SZ;
            break;
        }
        // else
        // {
        //     // clear_rx_buffer();
        //     // Ymodem_Printf((uint8_t[]){(uint8_t)RYM_CODE_NAK}, 1);
        //     // if (ucCanErrCount++ > RYM_ERRPACKNUM)
        //     // {
        //         return -RYM_ERR_CODE; // 错误的操作码
        //     //}
        //     continue;
        // }
    }

    //ucCanErrCount = 0;

    //printf("uldata_sz = %ld code = %d i = %d   TimerOut = %ld Ymodem_Malloc\r\n", uldata_sz, code, i, TimerOut);
    if (i == TimerOut)
    {
        return -RYM_ERR_TMO;
    }

    i = 0;

    pxRYM_Ag->buf = Ymodem_Malloc(uldata_sz);
    if (pxRYM_Ag->buf == NULL)
    {
        return -RYM_ENOMEM; // 内存不足错误
    }

    pxRYM_Ag->buf[0] = code;
    ulDataLen = RYM_ReadData(pxRYM_Ag->buf + 1, uldata_sz - 1, RYM_TRANTIMEROUT);
   //  printf("code = %x i = %x   TimerOut = %x ulDataLen = %ld\r\n", pxRYM_Ag->buf[0], pxRYM_Ag->buf[1], pxRYM_Ag->buf[uldata_sz - 1], ulDataLen);
    if (ulDataLen != (uldata_sz - 1))
    {
        return -RYM_ERR_DSZ;
    }

    if (pxRYM_Ag->buf[1] != 0x00 || pxRYM_Ag->buf[2] != 0xff)
    {
        return -RYM_ERR_SEQ;
    }

    recv_crc = (uint16_t)((pxRYM_Ag->buf[uldata_sz - 2] << 8) | (pxRYM_Ag->buf[uldata_sz - 1]));
    cal_crc = CRC16(&(pxRYM_Ag->buf[3]), uldata_sz - 5);
     printf("recv_crc = %d cal_crc = %d\r\n", recv_crc, cal_crc);
    if (recv_crc != cal_crc)
    {
        return -RYM_ERR_CRC;
    }

    if (pxRYM_Ag->on_begin && pxRYM_Ag->on_begin(pxRYM_Ag, pxRYM_Ag->buf + 3, uldata_sz - 5) != RYM_CODE_ACK)
    {
        return -RYM_ERR_CAN;
    }

    return RYM_OK;
}

static int RYM_ReadTrans_Data(RYM_t *pxRYM_Ag, uint32_t uldata_sz, enum rym_code *code)
{
    uint16_t recv_crc = 0;
    uint16_t cal_crc = 0;
    uint32_t ulDataLen = 0;

    pxRYM_Ag->buf = Ymodem_Malloc(uldata_sz);
    if (pxRYM_Ag->buf == NULL)
    {
        return -RYM_ENOMEM; // 内存不足错误
    }
    pxRYM_Ag->buf[0] = *code;

    ulDataLen = RYM_ReadData(pxRYM_Ag->buf + 1, uldata_sz - 1, RYM_TRANTIMEROUT);
    // ESP_LOGI("123", "ulDataLen %ld uldata_sz %ld \r\n",ulDataLen,uldata_sz);
    if (ulDataLen != (uldata_sz - 1))
    {
        return -RYM_ERR_DSZ;
    }

    if ((pxRYM_Ag->buf[1] + pxRYM_Ag->buf[2]) != 0xff)
    {
        return -RYM_ERR_SEQ;
    }
    // 检查是否在握手阶段，由于可能发送多余的 'C' 导致重新传输，忽略重复包
    if (pxRYM_Ag->stage == RYM_STAGE_ESTABLISHED && pxRYM_Ag->buf[1] == 0x00)
    {
        *code = RYM_CODE_NONE;
        return RYM_OK;
    }
    pxRYM_Ag->stage = RYM_STAGE_TRANSMITTING;

    recv_crc = (uint16_t)((pxRYM_Ag->buf[uldata_sz - 2] << 8) | (pxRYM_Ag->buf[uldata_sz - 1]));
    cal_crc = CRC16(&(pxRYM_Ag->buf[3]), uldata_sz - 5);
    if (recv_crc != cal_crc)
    {
        return -RYM_ERR_CRC;
    }

    if (pxRYM_Ag->on_data)
    {
        *code = pxRYM_Ag->on_data(pxRYM_Ag, pxRYM_Ag->buf + 3, uldata_sz - 5);
    }
    else
    {
        *code = RYM_CODE_ACK;
    }
    return RYM_OK;
}

static int RYMReadTrans(RYM_t *pxRYM_Ag)
{
    enum rym_code code = 0;
    uint32_t uldata_sz = 0;
    uint8_t ucCanErrCount = 0;

    Ymodem_Printf((uint8_t[]){(uint8_t)RYM_CODE_ACK}, 1);
    Ymodem_Printf((uint8_t[]){(uint8_t)RYM_CODE_C}, 1);

    pxRYM_Ag->stage = RYM_STAGE_ESTABLISHED;
    while (1)
    {
        int Rtu;
        RYM_ReadData((uint8_t *)&code, 1, RYM_TRANTIMEROUT);
        // ESP_LOGI("", "code = %d\r\n", code);
        switch (code)
        {
        case RYM_CODE_SOH:
            uldata_sz = _RYM_SOH_PKG_SZ; // SOH 包，128字节数据块
            break;
        case RYM_CODE_STX:
            uldata_sz = _RYM_STX_PKG_SZ; // STX 包，1024字节数据块
            break;
        case RYM_CODE_EOT:
            return RYM_OK; // 传输结束

        default:
            clear_rx_buffer();
            Ymodem_Printf((uint8_t[]){(uint8_t)RYM_CODE_NAK}, 1);
            if (ucCanErrCount++ > RYM_ERRPACKNUM)
            {
                return -RYM_ERR_CODE; // 错误的操作码
            }
        };

        ucCanErrCount = 0;
        Rtu = RYM_ReadTrans_Data(pxRYM_Ag, uldata_sz, &code);
        if (pxRYM_Ag->buf != NULL)
        {
            Ymodem_Free(pxRYM_Ag->buf);
            pxRYM_Ag->buf = NULL;
        }
        if (Rtu != RYM_OK)
        {
            return Rtu;
        }

        // 根据回调返回值决定是否继续或取消传输
        switch (code)
        {
        case RYM_CODE_CAN:
            // 按协议要求发送多个 CAN 结束传输
            for (int i = 0; i < RYM_END_SESSION_SEND_CAN_NUM; i++)
            {
                Ymodem_Printf((uint8_t[]){(uint8_t)RYM_CODE_CAN}, 1);
            }
            return -RYM_ERR_CAN; // 传输被取消
        case RYM_CODE_ACK:
            Ymodem_Printf((uint8_t[]){(uint8_t)RYM_CODE_ACK}, 1);

            break;
        default:
            /**这里的错误代码  是下位机决定的 */
            // 错误的操作码
            break;
        };
    }
}

// 滑动窗口法
static bool has_consecutive_zeros(uint8_t *arr, int size, int length)
{
    int zero_count = 0;

    for (int i = 0; i < size; i++)
    {
        if (arr[i] == 0)
        {
            zero_count++; // 连续零的计数
        }
        else
        {
            zero_count = 0; // 重置计数
        }

        // 如果找到连续的零，返回 true
        if (zero_count >= length)
        {
            return true;
        }
    }

    return false; // 没有找到连续的零
}

static int RYM_ReadFin(RYM_t *pxRYM_Ag)
{
    uint32_t ulDataLen = 0;
    uint32_t uldata_sz = 0;
    enum rym_code code = 0;
    uint16_t recv_crc = 0;
    uint16_t cal_crc = 0;
    uint8_t ucCanErrCount = 0;

    pxRYM_Ag->stage = RYM_STAGE_FINISHING;

    Ymodem_Printf((uint8_t[]){(uint8_t)RYM_CODE_NAK}, 1);

    ulDataLen = RYM_ReadData((uint8_t *)&code, 1, RYM_TRANTIMEROUT);
    if (code != RYM_CODE_EOT)
    {

        clear_rx_buffer();
        Ymodem_Printf((uint8_t[]){(uint8_t)RYM_CODE_NAK}, 1);
        if (ucCanErrCount++ > RYM_ERRPACKNUM)
        {
            return -RYM_ERR_CODE; // 错误的操作码
        }
    }
    ucCanErrCount = 0;
    Ymodem_Printf((uint8_t[]){(uint8_t)RYM_CODE_ACK}, 1);
    Ymodem_Printf((uint8_t[]){(uint8_t)RYM_CODE_C}, 1);
    ulDataLen = RYM_ReadData((uint8_t *)&code, 1, RYM_TRANTIMEROUT);

    switch (code)
    {
    case RYM_CODE_SOH:
        uldata_sz = _RYM_SOH_PKG_SZ;
        break;
    case RYM_CODE_STX:
        uldata_sz = _RYM_STX_PKG_SZ;
        break;
    default:
        clear_rx_buffer();
        Ymodem_Printf((uint8_t[]){(uint8_t)RYM_CODE_NAK}, 1);
        if (ucCanErrCount++ > RYM_ERRPACKNUM)
        {
            return -RYM_ERR_CODE; // 错误的操作码
        }
        break;
    }

    ucCanErrCount = 0;
    pxRYM_Ag->buf = Ymodem_Malloc(uldata_sz);
    if (pxRYM_Ag->buf == NULL)
    {
        return -RYM_ENOMEM; // 内存不足错误
    }
    pxRYM_Ag->buf[0] = code;

    ulDataLen = RYM_ReadData(pxRYM_Ag->buf + 1, uldata_sz - 1, RYM_TRANTIMEROUT);

    if (ulDataLen != (uldata_sz - 1))
    {
        return -RYM_ERR_DSZ;
    }

    if (pxRYM_Ag->buf[1] != 0x00 || pxRYM_Ag->buf[2] != 0xff)
    {
        return -RYM_ERR_SEQ;
    }

    recv_crc = (uint16_t)((pxRYM_Ag->buf[uldata_sz - 2] << 8) | (pxRYM_Ag->buf[uldata_sz - 1]));
    cal_crc = CRC16(&(pxRYM_Ag->buf[3]), uldata_sz - 5);

    if (recv_crc != cal_crc)
    {
        return -RYM_ERR_CRC;
    }

    // 准备下一次文件传输   第二个文件  批量传输文件的时候 有用
    if (!has_consecutive_zeros(pxRYM_Ag->buf, uldata_sz, uldata_sz - 5))
    {
        if (pxRYM_Ag->on_begin && pxRYM_Ag->on_begin(pxRYM_Ag, pxRYM_Ag->buf + 3, uldata_sz - 5) != RYM_CODE_ACK)
            return -RYM_ERR_CAN; // 传输被取消
        return RYM_OK;
    }
    // 传输完成
    pxRYM_Ag->stage = RYM_STAGE_FINISHED;

    // 发送最后一个 ACK
    Ymodem_Printf((uint8_t[]){(uint8_t)RYM_CODE_ACK}, 1);
    Ymodem_Printf((uint8_t[]){(uint8_t)RYM_CODE_O}, 1);
    if (pxRYM_Ag->on_end)
    {
        pxRYM_Ag->on_end(pxRYM_Ag, pxRYM_Ag->buf + 3, uldata_sz - 5);
    }
    return RYM_OK;
}

int RYM_ReadFile(RYM_t *pxRYM_Ag,
                 rym_callback on_begin,
                 rym_callback on_data,
                 rym_callback on_end)
{
    int err;
    pxRYM_Ag->on_begin = on_begin;
    pxRYM_Ag->on_data = on_data;
    pxRYM_Ag->on_end = on_end;
    pxRYM_Ag->stage = RYM_STAGE_NONE;

    err = RYM_Readhandshake(pxRYM_Ag, (RYM_READHANDSHAKE * 1000 / RYM_CHD_INTV_TICK));

    if (pxRYM_Ag->buf != NULL)
    {
        Ymodem_Free(pxRYM_Ag->buf);
        pxRYM_Ag->buf = NULL;
    }

    if (err != RYM_OK)
    {
        return err;
    }

    /*接收数据*/
    while (1)
    {
        err = RYMReadTrans(pxRYM_Ag);
        if (err != RYM_OK)
        {

            return err;
        }

        err = RYM_ReadFin(pxRYM_Ag);
        if (pxRYM_Ag->buf != NULL)
        {
            Ymodem_Free(pxRYM_Ag->buf);
            pxRYM_Ag->buf = NULL;
        }
        if (err != RYM_OK)
        {

            return err;
        }
        if (pxRYM_Ag->stage == RYM_STAGE_FINISHED)
            break;
    }

    return err;
}

static int RYM_SendPacket(RYM_t *pxRYM_Ag, uint8_t ucCode, uint8_t ucIndex, uint16_t ulDataSize)
{
    uint8_t ucIndex_inv = ~ucIndex;
    uint16_t send_crc;

    send_crc = CRC16(pxRYM_Ag->buf + 3, ulDataSize - 5);
    pxRYM_Ag->buf[0] = ucCode;
    pxRYM_Ag->buf[1] = ucIndex;
    pxRYM_Ag->buf[2] = ucIndex_inv;
    pxRYM_Ag->buf[ulDataSize - 2] = (uint8_t)(send_crc >> 8);
    pxRYM_Ag->buf[ulDataSize - 1] = (uint8_t)send_crc & 0xff;

    Ymodem_Printf(pxRYM_Ag->buf, ulDataSize);
    return 0;
}

static int RYM_Sendhandshake(RYM_t *pxRYM_Ag, uint32_t TimerOut)
{
    uint16_t ucData_sz = _RYM_SOH_PKG_SZ;
    pxRYM_Ag->stage = RYM_STAGE_ESTABLISHING;
    // uint32_t ulData_Sz = RYM_SENDPACKSPE;
    uint8_t ucCode = 0;
    int i = 0;

    for (i = 0; i < TimerOut; i++)
    {
        RYM_ReadData((uint8_t *)&ucCode, 1, RYM_CHD_INTV_TICK);
        if (ucCode == RYM_CODE_C)
        {
            break;
        }
    }
    if (i == TimerOut)
    {
        return -RYM_ERR_TMO; // 超时错误
    }

    if (pxRYM_Ag->on_begin && pxRYM_Ag->on_begin(pxRYM_Ag, pxRYM_Ag->buf + 3, ucData_sz - 5) != RYM_CODE_ACK)
    {
        return -RYM_ERR_CODE;
    }

    RYM_SendPacket(pxRYM_Ag, RYM_CODE_SOH, 0, ucData_sz);
    // printf("ulData_Sz = %d\r\n",ucData_sz);
    ucCode = 0;
    RYM_ReadData((uint8_t *)&ucCode, 1, RYM_TRANTIMEROUT);

    if (ucCode != RYM_CODE_ACK)
    {
        return -RYM_ERR_ACK; // ACK错误
    }

    RYM_ReadData((uint8_t *)&ucCode, 1, RYM_TRANTIMEROUT);

    if (ucCode != RYM_CODE_C)
    {
        return -RYM_ERR_ACK; // ACK错误
    }
    pxRYM_Ag->stage = RYM_STAGE_ESTABLISHED;

    return RYM_OK;
}

static int RYMSendTrans(RYM_t *pxRYM_Ag)
{

    uint8_t ucCode = 0;
    uint8_t ucCodeLen = 0;
    uint8_t ulIndex = 1;
    pxRYM_Ag->stage = RYM_STAGE_TRANSMITTING;

    if (RYM_SENDPACKSPE == _RYM_SOH_PKG_SZ - 5)
    {
        ucCodeLen = RYM_CODE_SOH;
    }
    else if (RYM_SENDPACKSPE == _RYM_STX_PKG_SZ - 5)
    {
        ucCodeLen = RYM_CODE_STX;
    }

    while (1)
    {
        ucCode = 0;

        if (ucCode == RYM_CODE_ACK || ucCode == 0 /*第一次进入*/)
        {
            if (pxRYM_Ag->on_data && pxRYM_Ag->on_data(pxRYM_Ag, pxRYM_Ag->buf + 3, RYM_SENDPACKSPE) != RYM_CODE_ACK)
            {
                return -RYM_ERR_CODE;
            }

            RYM_SendPacket(pxRYM_Ag, ucCodeLen, ulIndex, RYM_SENDPACKSPE + 5);

            ulIndex++;
        }
        else if (ucCode == RYM_CODE_NAK)
        {
            RYM_SendPacket(pxRYM_Ag, ucCodeLen, ulIndex, RYM_SENDPACKSPE + 5);
        }
        else
        {

            return -RYM_ERR_ACK; // ACK错误
        }
        RYM_ReadData((uint8_t *)&ucCode, 1, RYM_TRANTIMEROUT);
        if (pxRYM_Ag->stage == RYM_STAGE_FINISHING && ucCode == RYM_CODE_ACK)
        {
            Ymodem_Printf((uint8_t[]){(uint8_t)RYM_CODE_EOT}, 1);
            break;
        }
    }
    return RYM_OK;
}

static int RYM_SendFin(RYM_t *pxRYM_Ag)
{
    uint8_t ucCode = 0;

    RYM_ReadData((uint8_t *)&ucCode, 1, RYM_TRANTIMEROUT);
    if (ucCode != RYM_CODE_NAK)
    {
        return -RYM_ERR_ACK; // NAK 错误
    }
    Ymodem_Printf((uint8_t[]){(uint8_t)RYM_CODE_EOT}, 1);
    RYM_ReadData((uint8_t *)&ucCode, 1, RYM_TRANTIMEROUT);
    if (ucCode != RYM_CODE_ACK)
    {
        return -RYM_ERR_ACK; // NAK 错误
    }
    RYM_ReadData((uint8_t *)&ucCode, 1, RYM_TRANTIMEROUT);
    if (ucCode != RYM_CODE_C)
    {
        return -RYM_ERR_ACK; // NAK 错误
    }

    // 调用 on_end 回调函数，如果有的话  结束帧
    if (pxRYM_Ag->on_end && pxRYM_Ag->on_end(pxRYM_Ag, pxRYM_Ag->buf + 3, _RYM_SOH_PKG_SZ - 5) != RYM_CODE_ACK)
        return -RYM_ERR_CODE;

    ucCode = RYM_CODE_SOH;
    RYM_SendPacket(pxRYM_Ag, ucCode, 0, _RYM_SOH_PKG_SZ);
    pxRYM_Ag->stage = RYM_STAGE_FINISHED;

    return RYM_OK;
}

int RYM_SendFile(RYM_t *pxRYM_Ag,
                 rym_callback on_begin,
                 rym_callback on_data,
                 rym_callback on_end)
{
    int err;

    pxRYM_Ag->on_begin = on_begin;
    pxRYM_Ag->on_data = on_data;
    pxRYM_Ag->on_end = on_end;
    pxRYM_Ag->stage = RYM_STAGE_NONE;

    pxRYM_Ag->buf = Ymodem_Malloc(_RYM_SOH_PKG_SZ);
    if (pxRYM_Ag->buf == NULL)
    {
        return -RYM_ENOMEM; // 内存不足错误
    }

    err = RYM_Sendhandshake(pxRYM_Ag, (RYM_SENDHANDSHAKE * 1000 / RYM_CHD_INTV_TICK));

    if (pxRYM_Ag->buf != NULL)
    {
        Ymodem_Free(pxRYM_Ag->buf);
        pxRYM_Ag->buf = NULL;
    }

    if (err != RYM_OK)
    {

        return err;
    }
    pxRYM_Ag->buf = Ymodem_Malloc(RYM_SENDPACKSPE + 5);

    if (pxRYM_Ag->buf == NULL)
    {
        return -RYM_ENOMEM; // 内存不足错误
    }

    err = RYMSendTrans(pxRYM_Ag);

    if (pxRYM_Ag->buf != NULL)
    {
        Ymodem_Free(pxRYM_Ag->buf);
        pxRYM_Ag->buf = NULL;
    }

    if (err != RYM_OK)
    {
        return err;
    }
    pxRYM_Ag->buf = Ymodem_Malloc(_RYM_SOH_PKG_SZ);

    if (pxRYM_Ag->buf == NULL)
    {
        return -RYM_ENOMEM; // 内存不足错误
    }

    RYM_SendFin(pxRYM_Ag);
    if (pxRYM_Ag->buf != NULL)
    {
        Ymodem_Free(pxRYM_Ag->buf);
        pxRYM_Ag->buf = NULL;
    }

    return RYM_OK;
}
